import { NextRequest, NextResponse } from "next/server"; import { prisma } from "@/lib/prisma"; import { getThumbnail, loadFileData } from "@/lib/storage"; // Largeurs autorisées pour les rendus redimensionnés (évite la génération arbitraire) const ALLOWED_WIDTHS = [200, 400, 800, 1280, 2048]; export async function GET( request: NextRequest, { params }: { params: { id: string } } ) { const file = await prisma.file.findUnique({ where: { id: params.id } }); if (!file) { return NextResponse.json({ error: "File not found" }, { status: 404 }); } // --- Rendu image redimensionné (miniature / version viewer) --- const wParam = request.nextUrl.searchParams.get("w"); if (wParam && file.mimeType.startsWith("image/") && file.mimeType !== "image/svg+xml") { const requested = parseInt(wParam, 10); const width = ALLOWED_WIDTHS.find((w) => w >= requested) ?? ALLOWED_WIDTHS[ALLOWED_WIDTHS.length - 1]; try { const webp = await getThumbnail(file.storagePath, file.id, width, file.isEncrypted); return new NextResponse(new Uint8Array(webp), { headers: { "Content-Type": "image/webp", "Content-Length": String(webp.length), // Miniatures quasi-immuables (clé = id+largeur), cache agressif navigateur "Cache-Control": "private, max-age=604800", }, }); } catch { // En cas d'échec sharp on retombe sur l'original ci-dessous } } // --- Fichier original (déchiffré au repos) --- const data = await loadFileData(file.storagePath, file.isEncrypted); return new NextResponse(new Uint8Array(data), { headers: { "Content-Type": file.mimeType, "Content-Disposition": `inline; filename="${encodeURIComponent(file.name)}"`, "Content-Length": String(data.length), "Cache-Control": "private, max-age=3600", }, }); }